<!--
  Entity Clustering Demo Component

  This demo shows how to use entity clustering in CesiumJS to improve performance
  when displaying large numbers of entities. Clustering groups nearby entities
  into a single entity when zoomed out, and separates them when zoomed in.

  Features:
    - Billboard clustering
    - Label clustering
    - Point clustering
    - Custom cluster styling
-->

<template>
  <div class="demo-container">
    <BaseCesiumViewer 
      ref="cesiumViewer" 
      
      @viewer-ready="onViewerReady"
    />
    <div class="control-panel">
      <h3>Clustering Controls</h3>
      
      <div class="control-group">
        <h4>Clustering Settings</h4>
        <ControlItem
          type="checkbox"
          label="Enable Clustering"
          :value="clusteringSettings.enabled"
          label-after
          @update:value="clusteringSettings.enabled = $event"
          @change="updateClusteringSettings"
        />
        
        <ControlItem
          type="range"
          label="Pixel Range: {{ clusteringSettings.pixelRange }}"
          :value="clusteringSettings.pixelRange"
          :min="1"
          :max="100"
          :step="1"
          @update:value="clusteringSettings.pixelRange = $event"
          @input="updateClusteringSettings"
        />
        
        <ControlItem
          type="range"
          label="Minimum Cluster Size: {{ clusteringSettings.minimumClusterSize }}"
          :value="clusteringSettings.minimumClusterSize"
          :min="2"
          :max="20"
          :step="1"
          @update:value="clusteringSettings.minimumClusterSize = $event"
          @input="updateClusteringSettings"
        />
      </div>
      
      <div class="control-group">
        <h4>Cluster Styling</h4>
        <ControlItem
          type="range"
          label="Cluster Size: {{ clusterStyle.pixelSize }}"
          :value="clusterStyle.pixelSize"
          :min="10"
          :max="50"
          :step="1"
          @update:value="clusterStyle.pixelSize = $event"
          @input="updateClusterStyle"
        />
        
        <ControlItem
          type="range"
          label="Cluster Alpha: {{ clusterStyle.alpha.toFixed(2) }}"
          :value="clusterStyle.alpha"
          :min="0.1"
          :max="1"
          :step="0.05"
          @update:value="clusterStyle.alpha = $event"
          @input="updateClusterStyle"
        />
        
        <ControlItem
          type="select"
          label="Cluster Color"
          :value="clusterStyle.color"
          @update:value="clusterStyle.color = $event"
          @change="updateClusterStyle"
        >
          <option value="YELLOW">Yellow</option>
          <option value="RED">Red</option>
          <option value="BLUE">Blue</option>
          <option value="GREEN">Green</option>
          <option value="WHITE">White</option>
        </ControlItem>
      </div>
      
      <div class="control-group">
        <h4>Label Settings</h4>
        <ControlItem
          type="range"
          label="Font Size: {{ labelSettings.fontSize }}px"
          :value="labelSettings.fontSize"
          :min="12"
          :max="36"
          :step="1"
          @update:value="labelSettings.fontSize = $event"
          @input="updateLabelStyle"
        />
        
        <ControlItem
          type="range"
          label="Outline Width: {{ labelSettings.outlineWidth }}"
          :value="labelSettings.outlineWidth"
          :min="1"
          :max="5"
          :step="1"
          @update:value="labelSettings.outlineWidth = $event"
          @input="updateLabelStyle"
        />
      </div>
      
      <button @click="resetToDefaults" class="reset-button">Reset to Defaults</button>
    </div>
  </div>
</template>

<script>
import { reactive } from 'vue';
import BaseCesiumViewer from '../core/BaseCesiumViewer.vue';
import ControlItem from '../components/ControlItem.vue';

export default {
  name: 'EntityClusteringDemo',
  components: {
    BaseCesiumViewer,
    ControlItem
  },
  setup() {
    let viewer, Cesium;
    
    // Reactive settings for UI controls
    const clusteringSettings = reactive({
      enabled: true,
      pixelRange: 15,
      minimumClusterSize: 3
    });
    
    const clusterStyle = reactive({
      pixelSize: 20,
      alpha: 0.8,
      color: 'YELLOW'
    });
    
    const labelSettings = reactive({
      fontSize: 20,
      outlineWidth: 2
    });

    const onViewerReady = (payload) => {
      // Check if payload and viewer are valid
      if (!payload || !payload.viewer) {
        console.error('Viewer is not ready or payload is invalid');
        return;
      }
      
      viewer = payload.viewer;
      Cesium = payload.Cesium;
      
      // Enable clustering for the built-in data source
      viewer.dataSourceDisplay.defaultDataSource.clustering.enabled = clusteringSettings.enabled;
      viewer.dataSourceDisplay.defaultDataSource.clustering.pixelRange = clusteringSettings.pixelRange;
      viewer.dataSourceDisplay.defaultDataSource.clustering.minimumClusterSize = clusteringSettings.minimumClusterSize;
      
      // Handle cluster creation event
      viewer.dataSourceDisplay.defaultDataSource.clustering.clusterEvent.addEventListener(
        function(entities, cluster) {
          cluster.label.show = true;
          cluster.label.text = entities.length.toLocaleString();
          cluster.label.font = `${labelSettings.fontSize}px sans-serif`;
          cluster.label.fillColor = Cesium.Color.WHITE;
          cluster.label.outlineColor = Cesium.Color.BLACK;
          cluster.label.outlineWidth = labelSettings.outlineWidth;
          cluster.label.style = Cesium.LabelStyle.FILL_AND_OUTLINE;
          
          // Make the cluster point larger
          cluster.point.show = true;
          cluster.point.color = getColor(clusterStyle.color).withAlpha(clusterStyle.alpha);
          cluster.point.outlineColor = Cesium.Color.BLACK;
          cluster.point.outlineWidth = 2;
          cluster.point.pixelSize = clusterStyle.pixelSize;
        }
      );
      
      // Create many entities to demonstrate clustering
      const entityCount = 1000;
      for (let i = 0; i < entityCount; i++) {
        // Create random positions
        const longitude = -100 + (Math.random() * 20 - 10);
        const latitude = 35 + (Math.random() * 20 - 10);
        
        // Add billboard entity
        viewer.entities.add({
          name: `Entity ${i}`,
          position: Cesium.Cartesian3.fromDegrees(longitude, latitude),
          billboard: {
            image: './images/logo.png',
            scale: 0.5,
            color: Cesium.Color.fromRandom({
              alpha: 0.8
            })
          },
          label: {
            text: `Entity ${i}`,
            font: '12px sans-serif',
            fillColor: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            pixelOffset: new Cesium.Cartesian2(0, -15)
          },
          point: {
            pixelSize: 8,
            color: Cesium.Color.fromRandom({
              alpha: 0.8
            }),
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 1
          }
        });
      }
      
      // Set initial view to see clustering in action
      viewer.camera.setView({
        destination: Cesium.Cartesian3.fromDegrees(-100, 35, 10000000)
      });
    };
    
    // Helper function to get Cesium color from string
    const getColor = (colorName) => {
      switch (colorName) {
        case 'RED': return Cesium.Color.RED;
        case 'BLUE': return Cesium.Color.BLUE;
        case 'GREEN': return Cesium.Color.GREEN;
        case 'YELLOW': return Cesium.Color.YELLOW;
        case 'WHITE': return Cesium.Color.WHITE;
        default: return Cesium.Color.YELLOW;
      }
    };
    
    // Update clustering settings
    const updateClusteringSettings = () => {
      if (!viewer) return;
      
      viewer.dataSourceDisplay.defaultDataSource.clustering.enabled = clusteringSettings.enabled;
      viewer.dataSourceDisplay.defaultDataSource.clustering.pixelRange = clusteringSettings.pixelRange;
      viewer.dataSourceDisplay.defaultDataSource.clustering.minimumClusterSize = clusteringSettings.minimumClusterSize;
    };
    
    // Update cluster style
    const updateClusterStyle = () => {
      if (!viewer) return;
      
      // Trigger a redraw by temporarily disabling and re-enabling clustering
      const wasEnabled = viewer.dataSourceDisplay.defaultDataSource.clustering.enabled;
      viewer.dataSourceDisplay.defaultDataSource.clustering.enabled = false;
      
      // Use next tick to ensure the disable takes effect
      setTimeout(() => {
        viewer.dataSourceDisplay.defaultDataSource.clustering.enabled = wasEnabled;
      }, 0);
    };
    
    // Update label style
    const updateLabelStyle = () => {
      if (!viewer) return;
      
      // Trigger a redraw by temporarily disabling and re-enabling clustering
      const wasEnabled = viewer.dataSourceDisplay.defaultDataSource.clustering.enabled;
      viewer.dataSourceDisplay.defaultDataSource.clustering.enabled = false;
      
      // Use next tick to ensure the disable takes effect
      setTimeout(() => {
        viewer.dataSourceDisplay.defaultDataSource.clustering.enabled = wasEnabled;
      }, 0);
    };
    
    // Reset to defaults
    const resetToDefaults = () => {
      clusteringSettings.enabled = true;
      clusteringSettings.pixelRange = 15;
      clusteringSettings.minimumClusterSize = 3;
      
      clusterStyle.pixelSize = 20;
      clusterStyle.alpha = 0.8;
      clusterStyle.color = 'YELLOW';
      
      labelSettings.fontSize = 20;
      labelSettings.outlineWidth = 2;
      
      updateClusteringSettings();
      updateClusterStyle();
      updateLabelStyle();
    };

    return {
      clusteringSettings,
      clusterStyle,
      labelSettings,
      Math,
      onViewerReady,
      updateClusteringSettings,
      updateClusterStyle,
      updateLabelStyle,
      resetToDefaults
    };
  }
};
</script>

<style scoped>
.demo-container {
  position: relative;
  width: 100%;
  height: 100%;
}

.control-panel {
  position: absolute;
  top: 20px;
  right: 20px;
  width: 300px;
  max-height: calc(100% - 40px);
  background: rgba(40, 40, 40, 0.8);
  color: white;
  padding: 15px;
  border-radius: 5px;
  overflow-y: auto;
  z-index: 100;
  backdrop-filter: blur(5px);
}

.control-group {
  margin-bottom: 20px;
}

.control-group h4 {
  margin-top: 0;
  margin-bottom: 10px;
  border-bottom: 1px solid #666;
  padding-bottom: 5px;
}

.reset-button {
  width: 100%;
  padding: 10px;
  background: #2196f3;
  color: white;
  border: none;
  border-radius: 3px;
  cursor: pointer;
  font-weight: bold;
}

.reset-button:hover {
  background: #1976d2;
}
</style>